package com.huayun.netutil.net;

import java.util.HashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import com.huayun.netutil.NetInit;
import com.huayun.netutil.retrofit2.converter.string.StringConverterFactory;
import okhttp3.Dispatcher;
import okhttp3.OkHttpClient;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
import rx.Observable;
import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Func1;
import rx.schedulers.Schedulers;


/**
 * APIService
 * Created by LZL on 2017/1/23.
 */
public class APIService {
    private APIs apis;
    private Dispatcher dispatcher;
    public final static int BACK_PARSE_DATA = -1;//返回解析的数据
    public final static int BACK_STRING_DATA = 1;//返回没有解析的数据
    public final static String REQUEST_TYPE_JSON = "json";
    public final static String REQUEST_TYPE_OTHER = "other";

    private APIService(String baseUrl, int flag) {
        dispatcher = new Dispatcher(Executors.newFixedThreadPool(20));
        dispatcher.setMaxRequests(20);
        dispatcher.setMaxRequestsPerHost(1);

        OkHttpClient client = new OkHttpClient.Builder()
                .dispatcher(dispatcher)
                .connectTimeout(NetInit.getInstance().getDEFAULT_CONNECT_TIMEOUT(), TimeUnit.SECONDS)
                .readTimeout(NetInit.getInstance().getDEFAULT_READ_TIMEOUT(), TimeUnit.SECONDS)
                .writeTimeout(NetInit.getInstance().getDEFAULT_WRITE_TIMEOUT(), TimeUnit.SECONDS)
                .addInterceptor(new ErrorInterceptor())
                .build();
        Retrofit retrofit = null;
        if (flag == BACK_PARSE_DATA) {
            retrofit = new Retrofit.Builder()
                    .client(client)
                    .addConverterFactory(GsonConverterFactory.create())
                    .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                    .baseUrl(baseUrl)
                    .build();
        } else if (flag == BACK_STRING_DATA) {
            retrofit = new Retrofit.Builder()
                    .client(client)
                    .addConverterFactory(StringConverterFactory.create())
                    .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                    .baseUrl(baseUrl)
                    .build();
        }
        if (retrofit != null) {
            apis = retrofit.create(APIs.class);
        }
    }

    public static APIService getInstance() {
        return new APIService(NetInit.getInstance().getBASE_URL(), BACK_PARSE_DATA);
    }

    public static APIService getInstance(int flag) {
        return new APIService(NetInit.getInstance().getBASE_URL(), flag);
    }

    public static APIService getInstance(String baseUrl) {
        return new APIService(baseUrl, BACK_PARSE_DATA);
    }

    public static APIService getInstance(String baseUrl, int flag) {
        return new APIService(baseUrl, flag);
    }

    private <T> void toSubscribe(Observable<T> o, final Subscriber<T> s) {
        o.subscribeOn(Schedulers.io())
                .unsubscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(s);
    }

    private class resultFunc implements Func1<Object, Object> {
        @Override
        public Object call(Object result) {
            return result;
        }
    }

    @SuppressWarnings("unchecked")
    public void anyPost(HashMap<String, Object> params, String api, Subscriber<Object> subscriber) {
        this.anyPost(params, api, "", subscriber);
    }

    @SuppressWarnings("unchecked")
    public void anyPost(HashMap<String, Object> params, String api, String type, Subscriber<Object> subscriber) {
        if (apis != null) {
            params.put("UncertainURL", api);
            params.put("requestType", type);
            Observable observable = apis.anyPost(params).map(new resultFunc());
            toSubscribe(observable, subscriber);
        }
    }

    @SuppressWarnings("unchecked")
    public void anyGet(HashMap<String, Object> params, Subscriber<Object> subscriber) {
        if (apis != null) {
            Observable observable = apis.anyGet(params).map(new resultFunc());
            toSubscribe(observable, subscriber);
        }
    }
}
